package coop.bancocredicoop.proyectos.gd.servlet;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import coop.bancocredicoop.proyectos.gd.DateParser;
import coop.bancocredicoop.proyectos.gd.DocumentFile;
import coop.bancocredicoop.proyectos.gd.FrontEndMessage;
import coop.bancocredicoop.proyectos.gd.GDConfig;
import coop.bancocredicoop.proyectos.gd.LastSelectedValues;
import coop.bancocredicoop.proyectos.gd.ServletUtils;
import coop.bancocredicoop.proyectos.gd.Usuario;
import coop.bancocredicoop.proyectos.gd.fileListing.DocumentBrowser;
import coop.bancocredicoop.proyectos.gd.fileListing.InvalidFolderException;
import coop.bancocredicoop.proyectos.gd.service.DocumentCreationResult;
import coop.bancocredicoop.proyectos.gd.service.DocumentService;

public class DocumentServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	private static final Log log = LogFactory.getLog(DocumentServlet.class);
	private static final String listarArchivosJsp = "/jsp/listarArchivos/index.jsp";
	private static final String documentosRecientesJsp = "/jsp/documentosRecientes/index.jsp";
	private static final String altaDocumento = "/jsp/altaDocumento/index.jsp";

	@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		if (ServletUtils.isParameterEmpty(request, "fileName")) {
			getServletContext().getRequestDispatcher(listarArchivosJsp).forward(request, response);
		} else {
			getServletContext().getRequestDispatcher(altaDocumento).forward(request,response);
		}
		
    }
	
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		FrontEndMessage frontEndMessage = new FrontEndMessage();
		DocumentService documentService = new DocumentService();
		Date expirationDate = null;
		
		if (ServletUtils.isParameterEmpty(request, "customerId"))  {
			frontEndMessage.addErrorMessage("Debe ingresar un cliente");
		}

		if (ServletUtils.isParameterEmpty(request, "box"))  {
			frontEndMessage.addErrorMessage("Debe ingresar una caja");
		}

		try {
			expirationDate = DateParser.getDateFromString(request.getParameter("expirationDate"));
		} catch (ParseException e) {
			frontEndMessage.addErrorMessage("La fecha ingresada no es correcta");
		}
		
		if (frontEndMessage.hasErrors()) {
			reloadAfterErrors(request, response, frontEndMessage);
			return;
		}

        String baseDir = new GDConfig().getGrupoDocumentalIIConfig().getRepositoryPath();
        String fileName = request.getParameter("fileName");
        
		DocumentBrowser docBrowser = new DocumentBrowser(baseDir);
		try {
			docBrowser.validatePath(new File(baseDir, fileName).getCanonicalPath());
		} catch (InvalidFolderException e1) {
			log.error("Acceso invalido a: " + new File(baseDir, fileName).getCanonicalPath());
			response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
			return;
		}
        
        Long customerId = ServletUtils.getParameterAsLong(request, "customerId", null);
        String customerDescription = request.getParameter("customerDescription");
        Long documentTypeId = ServletUtils.getParameterAsLong(request, "documentType", null);
        String box = request.getParameter("box");
        DocumentFile documentFile = new DocumentFile(baseDir, fileName);        
        
        Usuario loggedInUser = (Usuario) request.getSession().getAttribute("usuario");
        Date now = new Date();
        String tags = ServletUtils.getParameterAsString(request, "tags");
        String notes = ServletUtils.getParameterAsString(request, "notes");
        boolean newVersionConfirmed = ServletUtils.getParameterAsBoolean(request, "newVersionConfirmed");
        Long realVersion = null;

        if (!newVersionConfirmed && 
            needsNewVersionConfirmation(documentService, customerId, documentTypeId)) {
        	frontEndMessage.addErrorMessage("Debe confirmar una nueva version");
        	request.getSession().setAttribute("needsNewVersionConfirmation", true);
        	try {
				reloadAfterErrors(request, response, frontEndMessage);
			} catch (Exception e) {
				String message = "Error redirigiendo para confirmar versión";
				log.error(message, e);
				throw new ServletException(message);
			}
        	return;
        }

        try {
            DocumentCreationResult result = documentService.createDocument(
                                       customerId, 
                                       box, 
                                       documentTypeId, 
                                       expirationDate, 
                                       tags, 
                                       documentFile,
                                       loggedInUser,
                                       now, 
                                       notes,
                                       realVersion);
            
            if (result.documentWasCreated()) {
                saveLastValues(request, new LastSelectedValues(customerId, customerDescription, box));
                String successMessage = String.format("Documento guardado exitosamente: %s", documentFile.getOriginalFilename());
                log.info(successMessage);
                frontEndMessage.setSuccessMessage(successMessage);
                request.setAttribute("document", result.getDocument());
            } else {
            	frontEndMessage.addErrorMessage("Se produjo un error: el documento no pudo guardarse");
            	reloadAfterErrors(request, response, frontEndMessage);
            	return;
            }
        } catch (Exception e) {
            frontEndMessage.addErrorMessage("Error guardando el documento");
            log.error("Error guardando el documento", e);
            reloadAfterErrors(request, response, frontEndMessage);
			return;
        }
        frontEndMessage.setMessagesInSession(request);
        response.sendRedirect(request.getContextPath() + documentosRecientesJsp);
	}

	private boolean needsNewVersionConfirmation(
			DocumentService documentService, Long customerId,
			Long documentTypeId) throws ServletException {
		
		try {
			return documentService.needsNewVersionConfirmation(customerId, documentTypeId);
		} catch (Exception e) {
			log.error("Error calling documentService.needsNewVersionConfirmation", e);
			throw new ServletException();
		}
	}
	
	private void reloadAfterErrors(HttpServletRequest request,
			HttpServletResponse response, FrontEndMessage frontEndMessage)
			throws IOException, ServletException {
		
		String expirationDateString = ServletUtils.getParameterAsString(request, "expirationDate");
		if (expirationDateString != null) {
			Date expirationDate;
			try {
				expirationDate = DateParser.getDateFromString(expirationDateString);
				Calendar cal = new GregorianCalendar();
				cal.setTime(expirationDate);
				request.setAttribute("expirationDateYear", String.format("%04d", cal.get(Calendar.YEAR)));
				request.setAttribute("expirationDateMonth", String.format("%02d", cal.get(Calendar.MONTH)));
				request.setAttribute("expirationDateDay", String.format("%02d", cal.get(Calendar.DAY_OF_MONTH)));
			} catch (ParseException e) {
				log.error("Error obteniendo fecha del parametro expirationDate", e);
			}
		}
		
		frontEndMessage.setMessagesInSession(request);
		request.getRequestDispatcher(altaDocumento).forward(request, response);
	}
	
	private void saveLastValues(HttpServletRequest request, LastSelectedValues values) {
	        
		HttpSession session = request.getSession();
		session.setAttribute("last", values);

	}
	
}
